import os
import sys
from xml.dom import minidom
import dbus.service

class LocalObjectStubProvider:
    
    def createProvider(confContext,  name):
        if name == "dbus":
            return DBusLocalObjectStubProvider(confContext)
    createProvider = staticmethod(createProvider)

class DBusLocalObjectStubProvider(LocalObjectStubProvider):
    
    def __init__(self,  confContext):
        registry_file_path = os.path.join(confContext.getConfRootPath(),  "dbus_wrapper_mappings.xml")
        xmldoc = minidom.parse(registry_file_path)
        self.__mappings = {}
        entries = xmldoc.getElementsByTagName("dbus_wrapper")
        for entry in entries:
            type = int(entry.getElementsByTagName("service-type")[0].firstChild.data)
            class_name = entry.getElementsByTagName("client-class-name")[0].firstChild.data
            self.__mappings[type] = class_name
        self.__bus = dbus.SessionBus()

    def __getClassByType(self,  type):
        name = self.__mappings[type]
        module = sys.modules["socf.client.local"]
        class_type = getattr(module,  name)
        return class_type
    
    def __splitURI(self,  serviceURI):
        busName = serviceURI[5:serviceURI.find('/')]
        servicePath = serviceURI[serviceURI.find('/'):]
        return (busName,  servicePath)

    def getServiceClientStub(self,  serviceType,  serviceURI):
        classType = self.__getClassByType(serviceType)
        params = self.__splitURI(serviceURI)
        localObject = classType(self.__bus, params[0],  params[1])
        return localObject

class DBusGpsServiceStub():
    
    def __init__(self, bus,  busName,  objectPath):
        service = bus.get_object(busName, objectPath)
        self.__getLocationRemote = service.get_dbus_method('getLocation', 'socf.getLocation')

    #returns GPS data
    def getLocation(self):
        return self.__getLocationRemote()
    
class DBusSonarServiceStub():
    
    def __init__(self, bus,  busName,  objectPath):
        service = bus.get_object(busName, objectPath)
        self.__getDistanceRemote = service. \
            get_dbus_method('getDistance', 'socf.getDistance')

    #returns distance
    def getDistance(self):
        return self.__getDistanceRemote()

class DBusCompassServiceStub():
    
    def __init__(self, bus,  busName,  objectPath):
        service = bus.get_object(busName, objectPath)
        self.__getDirectionRemote = service.get_dbus_method('getDirection', 'socf.getDirection')

    #returns direction
    def getDirection(self):
        return self.__getDirectionRemote()
        
class DBusMetalDetectorServiceStub():
    
    def __init__(self, bus,  busName,  objectPath):
        service = bus.get_object(busName, objectPath)
        self.__getMinesRemote = service.get_dbus_method('getMines', 'socf.getMines')

    def getMines(self):
        return self.__getMinesRemote()
    
class DBusNavServiceStub():
    
    def __init__(self, bus,  busName,  objectPath):
        service = bus.get_object(busName, objectPath)
        self.__moveUp = service.get_dbus_method('moveUp', 'socf.moveUp')
        self.__moveDown = service.get_dbus_method('moveDown', 'socf.moveDown')
        self.__moveLeft = service.get_dbus_method('moveLeft', 'socf.moveLeft')
        self.__moveRight = service.get_dbus_method('moveRight', 'socf.moveRight')
        self.__setSpeed = service.get_dbus_method('setSpeed', 'socf.setSpeed')
        self.__stop = service.get_dbus_method('stop', 'socf.stop')

    def moveUp(self):
        self.__moveUp()

    def moveDown(self):
        self.__moveDown()

    def moveLeft(self):
        self.__moveLeft()

    def moveRight(self):
        self.__moveRight()

    def setSpeed(self, speed):
        self.__setSpeed(speed)

    def stop(self):
        self.__stop()

class DBusDiscoveryServiceStub():
    
    def __init__(self, bus,  busName,  objectPath):
        service = bus.get_object(busName, objectPath)
        self.__getCurrentServicesList = service.get_dbus_method('getCurrentServicesList', 'socf.getCurrentServicesList')

    def getCurrentServicesList(self):
        return self.__getCurrentServicesList()
